const { EventEmitter } = require('events')

/**
 * 策略管理器
 *
 * 负责管理所有交易策略的注册、执行、冲突解决等
 * 实现策略链模式，支持优先级排序和并行执行
 */
class StrategyManager extends EventEmitter {
  constructor (config = {}) {
    super()

    this.config = {
      maxConcurrentStrategies: 10,
      executionTimeout: 30000,
      enableStatistics: true,
      logLevel: 'info',
      ...config
    }

    // 策略存储
    this.strategies = new Map()
    this.strategyChains = new Map()
    this.strategyGroups = new Map()

    // 执行统计
    this.executionStats = {
      totalExecutions: 0,
      successfulExecutions: 0,
      failedExecutions: 0,
      averageExecutionTime: 0,
      totalExecutionTime: 0,
      lastExecution: null
    }

    // 运行时状态
    this.isExecuting = false
    this.activeExecutions = new Map()

    this.emit('initialized', { config: this.config })
  }

  /**
   * 注册策略
   * @param {BaseStrategy} strategy 策略实例
   * @param {Object} options 注册选项
   */
  registerStrategy (strategy, options = {}) {
    if (!strategy || !strategy.name) {
      throw new Error('Invalid strategy: must have a name property')
    }

    if (this.strategies.has(strategy.name)) {
      throw new Error(`Strategy ${strategy.name} already registered`)
    }

    // 设置策略事件监听
    this.setupStrategyListeners(strategy)

    // 存储策略
    this.strategies.set(strategy.name, {
      instance: strategy,
      registeredAt: Date.now(),
      options: {
        group: options.group || 'default',
        autoStart: options.autoStart !== false,
        dependencies: options.dependencies || [],
        ...options
      }
    })

    // 添加到组
    const group = options.group || 'default'
    if (!this.strategyGroups.has(group)) {
      this.strategyGroups.set(group, new Set())
    }
    this.strategyGroups.get(group).add(strategy.name)

    this.emit('strategyRegistered', {
      strategyName: strategy.name,
      group,
      priority: strategy.config.priority
    })

    this.log('info', `Strategy ${strategy.name} registered in group ${group}`)
  }

  /**
   * 注销策略
   * @param {string} strategyName 策略名称
   */
  unregisterStrategy (strategyName) {
    const strategyData = this.strategies.get(strategyName)
    if (!strategyData) {
      throw new Error(`Strategy ${strategyName} not found`)
    }

    // 移除事件监听
    strategyData.instance.removeAllListeners()

    // 从组中移除
    const group = strategyData.options.group
    this.strategyGroups.get(group)?.delete(strategyName)

    // 移除策略
    this.strategies.delete(strategyName)

    this.emit('strategyUnregistered', { strategyName, group })
    this.log('info', `Strategy ${strategyName} unregistered`)
  }

  /**
   * 设置策略链
   * @param {string} chainName 链名称
   * @param {Array} strategyNames 策略名称数组
   * @param {Object} options 链选项
   */
  setStrategyChain (chainName, strategyNames, options = {}) {
    // 验证策略存在
    for (const name of strategyNames) {
      if (!this.strategies.has(name)) {
        throw new Error(`Strategy ${name} not registered`)
      }
    }

    // 按优先级排序
    const sortedStrategies = strategyNames.sort((a, b) => {
      const priorityA = this.strategies.get(a).instance.config.priority
      const priorityB = this.strategies.get(b).instance.config.priority
      return priorityB - priorityA // 高优先级在前
    })

    this.strategyChains.set(chainName, {
      strategies: sortedStrategies,
      options: {
        parallel: options.parallel || false,
        stopOnFirst: options.stopOnFirst || false,
        timeout: options.timeout || this.config.executionTimeout,
        ...options
      },
      createdAt: Date.now()
    })

    this.emit('chainCreated', { chainName, strategies: sortedStrategies })
    this.log('info', `Strategy chain ${chainName} created with ${sortedStrategies.length} strategies`)
  }

  /**
   * 执行策略链
   * @param {string} chainName 链名称
   * @param {Object} marketData 市场数据
   * @param {Object} analysisData 分析数据
   * @returns {Object|null} 执行结果
   */
  async executeStrategies (chainName, marketData, analysisData) {
    const startTime = Date.now()

    try {
      this.executionStats.totalExecutions++

      if (this.isExecuting && !this.config.allowConcurrentExecution) {
        this.log('warn', 'Strategy execution already in progress, skipping')
        return null
      }

      const chain = this.strategyChains.get(chainName)
      if (!chain) {
        throw new Error(`Strategy chain ${chainName} not found`)
      }

      this.isExecuting = true
      this.emit('executionStarted', { chainName, strategiesCount: chain.strategies.length })

      let results
      if (chain.options.parallel) {
        results = await this.executeStrategiesParallel(chain, marketData, analysisData)
      } else {
        results = await this.executeStrategiesSequential(chain, marketData, analysisData)
      }

      // 解决冲突
      const resolvedSignal = this.resolveConflicts(results, chainName)

      // 更新统计
      this.updateExecutionStats(startTime, results)

      this.emit('executionCompleted', {
        chainName,
        results: results.length,
        resolvedSignal: !!resolvedSignal,
        executionTime: Date.now() - startTime
      })

      return resolvedSignal
    } catch (error) {
      this.executionStats.failedExecutions++
      this.emit('executionError', {
        chainName,
        error: error.message,
        executionTime: Date.now() - startTime
      })

      this.log('error', `Strategy execution failed: ${error.message}`)
      throw error
    } finally {
      this.isExecuting = false
      this.executionStats.lastExecution = Date.now()
    }
  }

  /**
   * 并行执行策略
   * @private
   */
  async executeStrategiesParallel (chain, marketData, analysisData) {
    const promises = chain.strategies.map(async (strategyName) => {
      const strategyData = this.strategies.get(strategyName)
      if (!strategyData || !strategyData.instance.config.enabled) {
        return null
      }

      try {
        const executionId = `${strategyName}_${Date.now()}`
        this.activeExecutions.set(executionId, strategyName)

        const signal = await Promise.race([
          strategyData.instance.execute(marketData, analysisData),
          this.createTimeoutPromise(chain.options.timeout, strategyName)
        ])

        this.activeExecutions.delete(executionId)

        return signal ? {
          strategy: strategyName,
          signal,
          priority: strategyData.instance.config.priority,
          executionTime: Date.now()
        } : null
      } catch (error) {
        this.log('error', `Strategy ${strategyName} execution failed: ${error.message}`)
        return null
      }
    })

    const results = await Promise.all(promises)
    return results.filter(result => result !== null)
  }

  /**
   * 顺序执行策略
   * @private
   */
  async executeStrategiesSequential (chain, marketData, analysisData) {
    const results = []

    for (const strategyName of chain.strategies) {
      const strategyData = this.strategies.get(strategyName)
      if (!strategyData || !strategyData.instance.config.enabled) {
        continue
      }

      try {
        const executionId = `${strategyName}_${Date.now()}`
        this.activeExecutions.set(executionId, strategyName)

        const signal = await Promise.race([
          strategyData.instance.execute(marketData, analysisData),
          this.createTimeoutPromise(chain.options.timeout, strategyName)
        ])

        this.activeExecutions.delete(executionId)

        if (signal) {
          const result = {
            strategy: strategyName,
            signal,
            priority: strategyData.instance.config.priority,
            executionTime: Date.now()
          }

          results.push(result)

          // 如果设置了 stopOnFirst，找到第一个信号就停止
          if (chain.options.stopOnFirst) {
            break
          }
        }
      } catch (error) {
        this.log('error', `Strategy ${strategyName} execution failed: ${error.message}`)
        continue
      }
    }

    return results
  }

  /**
   * 解决策略冲突
   * @param {Array} results 策略执行结果
   * @param {string} chainName 链名称
   * @returns {Object|null} 解决后的信号
   */
  resolveConflicts (results, chainName) {
    if (results.length === 0) {
      this.emit('noSignalGenerated', { chainName })
      return null
    }

    if (results.length === 1) {
      return this.enrichResolvedSignal(results[0], { conflictResolution: 'single' })
    }

    // 按类型分组
    const grouped = this.groupResultsByType(results)

    // 如果有相反信号，使用优先级和置信度解决
    if (this.hasConflictingSignals(grouped)) {
      const resolved = this.resolveBuySellConflict(grouped)
      this.emit('conflictResolved', {
        chainName,
        totalSignals: results.length,
        conflictType: 'buy_sell',
        resolvedStrategy: resolved.strategy
      })
      return this.enrichResolvedSignal(resolved, { conflictResolution: 'priority_confidence' })
    }

    // 同类型信号，选择最强的
    const signalType = Object.keys(grouped)[0]
    const strongest = this.selectStrongestSignal(grouped[signalType])

    this.emit('conflictResolved', {
      chainName,
      totalSignals: results.length,
      conflictType: 'same_type',
      resolvedStrategy: strongest.strategy
    })

    return this.enrichResolvedSignal(strongest, { conflictResolution: 'strongest' })
  }

  /**
   * 按信号类型分组结果
   * @private
   */
  groupResultsByType (results) {
    const grouped = {}

    results.forEach(result => {
      const type = result.signal.type
      if (!grouped[type]) {
        grouped[type] = []
      }
      grouped[type].push(result)
    })

    return grouped
  }

  /**
   * 检查是否有冲突信号
   * @private
   */
  hasConflictingSignals (grouped) {
    const types = Object.keys(grouped)

    // 检查买卖冲突
    const hasBuy = types.some(type => ['BUY'].includes(type))
    const hasSell = types.some(type => ['SELL'].includes(type))

    // 检查平仓冲突
    const hasPingDuo = types.some(type => ['PING_DUO'].includes(type))
    const hasPingKong = types.some(type => ['PING_KONG'].includes(type))

    return (hasBuy && hasSell) || (hasPingDuo && hasPingKong)
  }

  /**
   * 解决买卖冲突
   * @private
   */
  resolveBuySellConflict (grouped) {
    const buySignals = grouped['BUY'] || []
    const sellSignals = grouped['SELL'] || []

    const strongestBuy = buySignals.length > 0 ? this.selectStrongestSignal(buySignals) : null
    const strongestSell = sellSignals.length > 0 ? this.selectStrongestSignal(sellSignals) : null

    if (!strongestBuy) return strongestSell
    if (!strongestSell) return strongestBuy

    // 比较综合得分
    const buyScore = this.calculateSignalScore(strongestBuy)
    const sellScore = this.calculateSignalScore(strongestSell)

    return buyScore > sellScore ? strongestBuy : strongestSell
  }

  /**
   * 选择最强信号
   * @private
   */
  selectStrongestSignal (signals) {
    if (signals.length === 1) return signals[0]

    return signals.reduce((strongest, current) => {
      const strongestScore = this.calculateSignalScore(strongest)
      const currentScore = this.calculateSignalScore(current)

      return currentScore > strongestScore ? current : strongest
    })
  }

  /**
   * 计算信号得分
   * @private
   */
  calculateSignalScore (result) {
    const signal = result.signal
    const priority = result.priority || 50
    const confidence = signal.confidence || 0.5
    const level = signal.level || 0

    // 综合得分：优先级40% + 置信度40% + 等级20%
    return (priority / 100) * 0.4 + confidence * 0.4 + (level / 2) * 0.2
  }

  /**
   * 丰富解决后的信号
   * @private
   */
  enrichResolvedSignal (result, resolutionInfo) {
    const signal = result.signal

    return {
      ...signal,
      metadata: {
        ...signal.metadata,
        resolvedBy: 'StrategyManager',
        originalStrategy: result.strategy,
        resolutionMethod: resolutionInfo.conflictResolution,
        resolvedAt: Date.now(),
        signalScore: this.calculateSignalScore(result)
      }
    }
  }

  /**
   * 创建超时Promise
   * @private
   */
  createTimeoutPromise (timeout, strategyName) {
    return new Promise((_, reject) => {
      setTimeout(() => {
        reject(new Error(`Strategy ${strategyName} execution timeout after ${timeout}ms`))
      }, timeout)
    })
  }

  /**
   * 更新执行统计
   * @private
   */
  updateExecutionStats (startTime, results) {
    const executionTime = Date.now() - startTime

    this.executionStats.successfulExecutions++
    this.executionStats.totalExecutionTime += executionTime
    this.executionStats.averageExecutionTime =
      this.executionStats.totalExecutionTime / this.executionStats.successfulExecutions
  }

  /**
   * 设置策略事件监听
   * @private
   */
  setupStrategyListeners (strategy) {
    strategy.on('signalGenerated', (signal) => {
      this.emit('strategySignalGenerated', {
        strategy: strategy.name,
        signal
      })
    })

    strategy.on('error', (error) => {
      this.emit('strategyError', {
        strategy: strategy.name,
        error
      })
    })

    strategy.on('executed', (data) => {
      this.emit('strategyExecuted', {
        strategy: strategy.name,
        ...data
      })
    })
  }

  /**
   * 获取策略列表
   * @param {string} group 策略组名称
   * @returns {Array} 策略列表
   */
  getStrategies (group = null) {
    const strategies = Array.from(this.strategies.entries()).map(([name, data]) => ({
      name,
      priority: data.instance.config.priority,
      enabled: data.instance.config.enabled,
      group: data.options.group,
      registeredAt: data.registeredAt
    }))

    return group ? strategies.filter(s => s.group === group) : strategies
  }

  /**
   * 获取活跃策略
   * @returns {Array} 活跃策略列表
   */
  getActiveStrategies () {
    return this.getStrategies().filter(s => s.enabled)
  }

  /**
   * 启用/禁用策略
   * @param {string} strategyName 策略名称
   * @param {boolean} enabled 是否启用
   */
  setStrategyEnabled (strategyName, enabled) {
    const strategyData = this.strategies.get(strategyName)
    if (!strategyData) {
      throw new Error(`Strategy ${strategyName} not found`)
    }

    if (enabled) {
      strategyData.instance.enable()
    } else {
      strategyData.instance.disable()
    }

    this.emit('strategyEnabledChanged', { strategyName, enabled })
  }

  /**
   * 获取执行统计信息
   * @returns {Object} 统计信息
   */
  getExecutionStatistics () {
    return {
      ...this.executionStats,
      registeredStrategies: this.strategies.size,
      activeStrategies: this.getActiveStrategies().length,
      strategyChains: this.strategyChains.size,
      isExecuting: this.isExecuting,
      activeExecutions: this.activeExecutions.size
    }
  }

  /**
   * 获取策略统计信息
   * @param {string} strategyName 策略名称
   * @returns {Object} 策略统计信息
   */
  getStrategyStatistics (strategyName) {
    const strategyData = this.strategies.get(strategyName)
    if (!strategyData) {
      throw new Error(`Strategy ${strategyName} not found`)
    }

    return strategyData.instance.getStatistics()
  }

  /**
   * 重置统计信息
   */
  resetStatistics () {
    this.executionStats = {
      totalExecutions: 0,
      successfulExecutions: 0,
      failedExecutions: 0,
      averageExecutionTime: 0,
      totalExecutionTime: 0,
      lastExecution: null
    }

    // 重置所有策略统计
    this.strategies.forEach((data) => {
      data.instance.resetStatistics()
    })

    this.emit('statisticsReset')
  }

  /**
   * 日志记录
   * @private
   */
  log (level, message, data = {}) {
    const logData = {
      timestamp: new Date().toISOString(),
      level,
      component: 'StrategyManager',
      message,
      ...data
    }

    this.emit('log', logData)

    // 简单的控制台输出
    if (this.config.logLevel === 'debug' ||
        (this.config.logLevel === 'info' && level !== 'debug') ||
        level === 'error') {
      console.log(`[${logData.timestamp}] ${level.toUpperCase()}: ${message}`)
    }
  }

  /**
   * 销毁管理器
   */
  destroy () {
    // 销毁所有策略
    this.strategies.forEach((data, name) => {
      try {
        data.instance.destroy()
      } catch (error) {
        this.log('error', `Error destroying strategy ${name}: ${error.message}`)
      }
    })

    // 清理资源
    this.strategies.clear()
    this.strategyChains.clear()
    this.strategyGroups.clear()
    this.activeExecutions.clear()

    // 移除所有监听器
    this.removeAllListeners()

    this.emit('destroyed')
  }
}

module.exports = StrategyManager
